import { useMemo, useReducer, useState, memo, useCallback, useRef, forwardRef, useImperativeHandle, Component } from 'react'
import BarChart from './components/BarChart'
import { Button, Input } from 'antd'

//1. 定义reducer函数，根据不同的action返回不同的状态
function reducer(state, action) {
  switch (action.type) {
    case 'INC':
      return state + 1
    case 'DEC':
      return state - 1
    case 'SET':
      return action.payload
    default:
      return 1
  }
}

// 计算斐波那契数列之和
function fib(n) {
  console.log('计算函数执行了')
  if (n < 3)
    return 1
  return fib(n - 2) + fib(n - 1)
}

// memo 进行缓存， 只有props 发生变化的时候才会重新渲染  // 默认机制 子跟着父
// bug：使用memo 放在home 还是会更新 但是放在home外面不会更新 ？
// 简单类型 React.memo props 变化重新渲染 
// 引用类型  新值和旧值的对比 传递新的引用 如果都是固定的引用，可使用useMemo
const MemoSon = memo(function Son({ count, list }) {
  console.log('我是子组件，我重新渲染了', count,)
  return <div>this is son={count}{list}</div>
})

// 子组件
const InputComponent = memo(function InputFn({ onChange }) {
  console.log('子组件渲染了～')
  return (
    <Input type='text' placeholder='请输入' onChange={(e) => onChange(e.target.value)} />
  )
})

// const Son = () => {
//   return <Input placeholde='请输入' />
// }
const Son = forwardRef((props, ref) => {
  return <Input placeholde='请输入' ref={ref} />
})
const SonUseImperative = forwardRef((props, ref) => {
  const inputRef = useRef(null)
  const focusHandler = () => {
    inputRef.current.focus()
  }
  // 把聚焦方法暴露出去
  useImperativeHandle(ref, () => {
    return {
      //暴露方法
      focusHandler
    }
  })
  return <Input placeholde='请输入' ref={inputRef} />
})
const Home = () => {
  // 2、组件中调用const [state,dispatch] = useReducer(state,0) 
  const [state, dispatch] = useReducer(reducer, 0)
  // 3、调用dispatch({type: 'INC'}}) 通知reducer产生新的状态使用这个状态 更新UI

  const [count1, setCount1] = useState(0)
  const [count2, setCount2] = useState(0)

  //计算大的 消耗性能的
  const result = useMemo(() => {
    // 返回计算得到的结果
    return fib(count1)
  }, [count1])

  const [count, setCount] = useState(0)
  const num = 100
  // const list = [1, 2, 3]
  const list = useMemo(() => {
    return [1, 2, 3]
  }, [])

  const handleChange = useCallback((value) => {
    console.log(value)
  }, [])

  const sonRef = useRef(null)
  const showRef = () => {
    console.log(sonRef)
    sonRef.current.focus()
  }
  const sonImRef = useRef(null)
  const showImRef = () => {
    console.log('sonImRef')
    console.log(sonImRef)
    sonImRef.current.focusHandler()
  }

  const [show, setShow] = useState(true)
  // 类组件
  class Counter extends Component {
    // 生命周期函数 组件渲染完毕执行 ajax 请求
    componentDidMount() {
      console.log('组件渲染完毕，请求发送')
      // 开启定时器
      this.timer = setInterval(() => {
        console.log('定时时运行')
      }, 1000)
    }
    //生命周期函数 组件卸载时自动执行 ，清除定时器 清除事件绑定
    componentWillUnmount() {
      console.log('组件卸载')
      clearInterval(this.timer)
    }
    // 1、状态变量
    state = {
      count: 0
    }
    //2、 事件回调
    handleCount = () => {
      this.setState({
        count: this.state.count + 1
      })
    }
    // 3、UI（JSX渲染）
    render() {
      return (
        <Button onClick={this.handleCount}>class自增{this.state.count}</Button>
      )
    }
  }

  //  类组件-子  子传父 方法
  class Children extends Component {
    state = {

    }

    render() {
      return (
        <div>我是子组件{this.props.msg}

          <Button onClick={() => this.props.onGetSonMsg('this is a son msg')}>set msg to Parent</Button>
        </div>

      )
    }

  }
  // 类组件 -父 父-传子 props 在子组件标签上调用这个函数传递参数
  class Parent extends Component {
    state = {
      msg: 'this is a parent'
    }

    getSonMsg = (son) => {
      console.log(son)
    }
    render() {
      return (
        <>
          我是父组件
          <Children msg={this.state.msg} onGetSonMsg={this.getSonMsg} />
        </>
      )
    }
  }
  return (
    <div>
      {state}
      <Button onClick={() => dispatch({ type: 'INC' })}>+</Button>
      <Button onClick={() => dispatch({ type: 'DEC' })}>-</Button>
      <Button onClick={() => dispatch({ type: "SET", payload: 100 })}>设置一百</Button>
      <Button onClick={() => setCount1(count1 + 1)}>change count1: {count1}</Button>
      <Button onClick={() => setCount2(count2 + 1)}>change count2: {count2}</Button>{result}
      <Button onClick={() => setCount(count + 1)}>增加</Button>
      <MemoSon list={list} count={num} />
      <InputComponent onChange={handleChange} />
      <div>
        <Son ref={sonRef} />
        <Button onClick={showRef}>showRef</Button>
      </div>
      <div>
        <SonUseImperative ref={sonImRef} />
        <Button onClick={showImRef}>父调子方法</Button>
      </div>
      <div>
        {show && <Counter />}
        <Button onClick={() => setShow(false)}>unMount</Button>
      </div>
      <div>
        {/* 类组件通讯 */}
        <Parent />
      </div>
      <BarChart title={'三大框架满意度'} />
      <BarChart title={'三大框架使用度'} />
    </div >
  )
}
export default Home